using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Data.Entity.Core.Objects.DataClasses;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Xml.Serialization;
using System.Web.Script.Serialization;

namespace System.Web.Mvc
{
    public class SerializationContext : IDisposable
    {
        public PropertyCache GetPropertyCache(Type type)
        {
            PropertyCache pc = null;
            if (!Cache.TryGetValue(type, out pc))
            {
                pc = PropertyCache.Create(type);
                Cache[type] = pc;
            }
            return pc;
        }

        [ThreadStatic]
        private static Stack<SerializationContext> _ContextStack;

        private Dictionary<Type, PropertyCache> Cache = new Dictionary<Type, PropertyCache>();

        public void Include<T>(params string[] properties)
        {
            Type type = typeof(T);
            Include(type, properties);
        }


        public void Include(Type type, params string[] properties)
        {
            PropertyCache pc = GetPropertyCache(type);
            pc.Show(properties);
        }

        public void Exclude<T>(params string[] properties)
        {
            Exclude(typeof(T), properties);
        }

        public void Exclude(Type type, params string[] properties)
        {
            PropertyCache pc = GetPropertyCache(type);
            pc.Hide(properties);
        }

        private SerializationContext(bool contextual)
        {
            if (!contextual)
                return;
            if (_ContextStack == null)
            {
                _ContextStack = new Stack<SerializationContext>();
            }
            _ContextStack.Push(this);
        }

        #region public void  Dispose()
        public void Dispose()
        {
            _ContextStack.Pop();
            if (_ContextStack.Count == 0)
                _ContextStack = null;
        }
        #endregion

        public static void Execute(Action a)
        {
            using (SerializationContext c = new SerializationContext(true))
            {
                a();
            }
        }

        private static SerializationContext _Default = new SerializationContext(false);

        public static SerializationContext Current
        {
            get
            {
                if (_ContextStack == null || _ContextStack.Count == 0)
                    return _Default;
                return _ContextStack.Peek();
            }
        }


    }
}
